Skip to content

feat(kmip): add token and AWS enrollment for KMIP server#254

Open
bernie-g wants to merge 12 commits into
mainfrom
bernie/kms-14-remove-machine-identities-from-kmip-server-registration
Open

feat(kmip): add token and AWS enrollment for KMIP server#254
bernie-g wants to merge 12 commits into
mainfrom
bernie/kms-14-remove-machine-identities-from-kmip-server-registration

Conversation

@bernie-g

@bernie-g bernie-g commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Description 📣

Adds --enroll-method=token|aws to infisical kmip start and kmip systemd install, so a KMIP server enrolls with a one-time token or AWS auth and reuses the derived access token across restarts; the legacy --identity-client-id/secret flow still works. Depends on a new infisical-kmip release — go.mod is still pinned to v0.3.17 and must be bumped before merge (currently builds via a local replace).

Type ✨

  • Bug fix
  • New feature
  • Improvement
  • Breaking change
  • Documentation

Tests 🛠️

Manually enrolled a KMIP server via token and AWS (including systemd install) against a local backend, verified registration and a real KMIP crypto op, and confirmed the legacy machine-identity flow still registers.


Adds --enroll-method=token|aws to 'kmip start' and 'kmip systemd install',
persisting and reusing the enrollment access token, alongside the existing
machine-identity flow.
@linear

linear Bot commented Jun 4, 2026

Copy link
Copy Markdown

KMS-14

@infisical-review-police

Copy link
Copy Markdown

💬 Discussion in Slack: #pr-review-cli-254-feat-kmip-add-token-and-aws-enrollment-for-kmip-server

Posted by Review Police — reviews, comments, new commits, and CI failures will stream into this channel.

@bernie-g bernie-g marked this pull request as ready for review June 4, 2026 14:27
@greptile-apps

greptile-apps Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds --enroll-method=token|aws to infisical kmip start and kmip systemd install, allowing a KMIP server to authenticate via a one-time enrollment token or AWS STS instead of the legacy machine-identity client ID/secret flow. Enrollment state (access token, server ID, domain) is persisted in a per-server conf file so long-lived access tokens survive restarts.

  • packages/kmip/enroll.go — new key/value store for enrollment state at ~/.infisical/kmip/<name>.conf (non-root) or /etc/infisical/kmip/<name>.conf (root), with 0600 permissions.
  • packages/kmip/aws_auth.go — builds and signs a presigned STS GetCallerIdentity request and forwards the signed headers to Infisical for AWS Auth; no real outbound STS call is made.
  • packages/kmip/systemd.go — refactored into shared helpers and adds two new systemd installer variants for token and AWS enrollment methods.

Confidence Score: 3/5

The new enrollment flows work correctly for the happy path, but there is a logic hole that produces a cryptic failure in a realistic recovery scenario, and the systemd env file writer does not sanitize values against newline injection.

The enrollment token reuse check in enrollKmipServer silently falls through to a doomed re-enrollment attempt when the token was already consumed but the access token was never persisted — a realistic edge case (e.g., disk-full or permission error on first run) that leaves the operator with no actionable error message. Additionally, user-supplied values are written verbatim into the systemd EnvironmentFile, enabling env-variable injection via newlines in flag values.

packages/cmd/kmip.go (enrollment token fallthrough logic) and packages/kmip/systemd.go (env-file value sanitization)

Security Review

  • Unvalidated domain as API endpoint (packages/cmd/kmip.go lines 79–85): The Infisical API URL is assembled from the --domain flag or the INFISICAL_KMIP_DOMAIN value read from the per-server conf file without hostname validation. If the conf file at /etc/infisical/kmip/<name>.conf or ~/.infisical/kmip/<name>.conf were modified, the server would transmit its access token and enrollment requests to an attacker-controlled host on the next restart.

Important Files Changed

Filename Overview
packages/cmd/kmip.go Core command handler for kmip start and kmip systemd install; adds token/AWS enrollment flows with a logic hole (fallthrough to re-enrollment with an already-spent token) and unvalidated domain used as the API endpoint.
packages/kmip/enroll.go New file: key/value config store for enrollment state (access token, enrollment token, server ID, domain) at ~/.infisical/kmip/<name>.conf or /etc/infisical/kmip/<name>.conf; file permissions are 0600, logic is correct.
packages/kmip/aws_auth.go New file: signs a presigned STS GetCallerIdentity request and forwards its headers to Infisical for AWS Auth enrollment; standard pattern, no actual outbound STS call is made.
packages/kmip/systemd.go Refactored into helpers (kmipCommonEnv, writeKmipSystemdService, systemdPreconditionsMet) and two new installers for token/AWS methods; env-file values are not sanitized against newline injection.
packages/api/api.go Adds CallKmipServerLogin following the same pattern as adjacent API calls; no issues found.
packages/api/model.go Adds KmipServerLoginRequest and KmipServerLoginResponse structs; straightforward, no issues.

Reviews (1): Last reviewed commit: "feat(kmip): add token and AWS enrollment..." | Re-trigger Greptile

Comment thread packages/cmd/kmip.go
Comment thread packages/kmip/systemd.go
Comment thread packages/cmd/kmip.go Outdated
Comment thread packages/kmip/aws_auth.go
payloadHash := fmt.Sprintf("%x", hash.Sum(nil))

signer := v4.NewSigner()
if err := signer.SignHTTP(ctx, awsCredentials, req, payloadHash, "sts", awsRegion, time.Now()); err != nil {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium: AWS enrollment proof is replayable

The SigV4 request only proves the AWS principal; kmipServerID is sent later as unsigned JSON. Anyone who obtains this enrollment payload can replay the same iamRequestBody and iamRequestHeaders with a different kmipServerId during the SigV4 validity window, authenticating this host to any KMIP server configuration that trusts the same AWS principal. Add a custom audience header containing the KMIP server ID before SignHTTP, forward it in IamRequestHeaders, and have the API verify that the signed header matches the JSON kmipServerId.

@veria-ai

veria-ai Bot commented Jun 4, 2026

Copy link
Copy Markdown

PR overview

This pull request adds token-based and AWS IAM-based enrollment support for a KMIP server, including AWS authentication request construction in the KMIP package.

One security issue remains open after one prior issue was addressed. The remaining concern is that the AWS enrollment proof binds only to the AWS principal and not to the target KMIP server ID, allowing a captured enrollment payload to be replayed against another trusted KMIP server configuration during the SigV4 validity window. Binding the KMIP server ID into the signed AWS request would close this replay path.

Open issues (1)

Fixed/addressed: 1 · PR risk: 6/10

Comment thread packages/api/api.go Outdated
bernie-g added 3 commits June 4, 2026 19:36
Picks up the published release with the AccessToken field, so the CLI builds
without the local replace directive.
For enrollment-based KMIP servers the cert config (hostnames/IPs, TTL, common name,
key algorithm) is configured in the UI and read by the daemon via /kmip/servers/connect,
so --hostnames-or-ips is no longer required at launch.
infisical kmip start/systemd install now take <server-name> as a positional argument,
e.g. 'infisical kmip start my-server'. The --server-name flag and INFISICAL_KMIP_SERVER_NAME
env var still work as alternatives; the name is required (no longer defaults to kmip-server).
Comment thread packages/cmd/kmip.go
bernie-g added 2 commits June 5, 2026 16:54
Picks up the /kmip/servers/connect daemon path so enrollment-based KMIP servers fetch
their certificate from the platform instead of passing cert config at launch.
The e2e module (replace infisical-merge => ../) still pinned infisical-kmip v0.3.17 as an
indirect dep, which left it un-tidy and failed the E2E 'go test' tidy check. Re-tidied to
v0.3.19 to match the root module.
Comment thread packages/cmd/kmip.go Outdated
Comment thread packages/cmd/kmip.go
if err := localkmip.InstallEnrolledKmipSystemdService(enrollResp.AccessToken, domain, listenAddress, serverName, certificateTTL, hostnamesOrIps); err != nil {
util.HandleError(err, "Failed to install systemd service")
}
case localkmip.EnrollMethodAws:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmm is it intended that AWS does no auth validation at install time? 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea this is the same way the gateway/relay do it

Comment thread packages/cmd/kmip.go Outdated
Comment thread packages/cmd/kmip.go Outdated
Comment thread packages/cmd/kmip.go Outdated
…egacy auth

When no enroll method is given, reuse the stored enrollment access token unless explicit
identity credentials were passed, rather than silently dropping to legacy machine-identity
auth. Mirrors the gateway's start behavior. Token systemd installs rely on this fallback
(the long-lived token is reused); the AWS path still persists the method to force STS re-auth.
@bernie-g bernie-g force-pushed the bernie/kms-14-remove-machine-identities-from-kmip-server-registration branch from 78972af to 87255b7 Compare June 8, 2026 14:19
bernie-g added 3 commits June 8, 2026 10:32
Both 'kmip start' and 'kmip systemd install' resolved + validated --enroll-method with the
same flag/env/validate block. Unify into resolveEnrollMethod (per review feedback).
Both commands resolved the Infisical domain differently (start: flag -> stored -> logged-in;
install: flag -> env). Extract one resolveDomain helper (flag -> stored -> logged-in -> env) used
by both, per review feedback. Behavior preserved: stored/logged-in are empty at a fresh install
so it stays flag -> env there, and env remains lowest priority at start.
… install

Both now read "Domain of your self-hosted Infisical instance", matching each other and the
gateway/relay flag wording.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants